package com.yiyw.herostory.factory;

import com.yiyw.herostory.handler.ICmdHandler;
import com.yiyw.herostory.util.PackageUtil;
import com.yiyw.herostory.util.ScanningFile;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Author yiyw
 * @Description 用户指令处理器工厂
 * @Date 2022/8/14 15:06
 **/
@Slf4j
public final class CmdHandlerFactory {

    private static Map<Class<?>, ICmdHandler> _map = new HashMap<>();

    /***
     * Title: init
     * @author yiyw
     * @description 初始化获取所有的 CMD 处理器
     * @createTime  2022/8/15 22:51
     *
     * @return void
     */
    public static void init() {
        log.info("start init CmdHandler.");
        // 获取指定类的所有子类
        ScanningFile scanningFile = new ScanningFile(ICmdHandler.class, ICmdHandler.class.getPackage().getName());
        Set<Class<?>> subClazz = scanningFile.eleStrategyList;;
        for (Class<?> clazz : subClazz) {
            if (clazz.isInterface()) {
                continue;
            }
            // 获取 handler 方法中的参数
            try {
                Method[] methods = clazz.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.getName().equals("handler") && !method.isBridge()) {
                        Parameter[] parameters = method.getParameters();
                        if (parameters.length != 2) {
                            continue;
                        }
                        Class<?> cmdType = parameters[1].getType();
                        ICmdHandler instance = (ICmdHandler) clazz.newInstance();
                        _map.put(cmdType, instance);
                        log.info("cmdType: {}  <===> cmdHandler: {}", cmdType, clazz);
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    public static ICmdHandler getHandler(Object msg) {
        if (null == msg) {
            return null;
        }
        ICmdHandler result = _map.get(msg.getClass());
        if (null == result) {
            log.error("无法匹配的消息处理器: {}", msg.getClass());
            return null;
        }
        return result;
    }
}
